package common

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os/user"
	"runtime"
	"strings"
)

// option 是用于自定义 http.Request 的函数类型。
// 可用于设置请求头、Token 等。
type option func(*http.Request)

// SetToken 返回一个设置 Bearer Token 的 option。
// 用法：SendHttp(url, data, SetToken("your_token"))
func SetToken(token string) option {
	return func(req *http.Request) {
		if token != "" {
			req.Header.Set("Authorization", "Bearer "+token)
		}
	}
}

// SetHeader 返回一个设置自定义 Header 的 option。
// 用法：SendHttp(url, data, SetHeader("X-My-Header", "value"))
func SetHeader(key, value string) option {
	return func(req *http.Request) {
		if key != "" && value != "" {
			req.Header.Set(key, value)
		}
	}
}

// SendHttp 发送 HTTP POST 请求，使用 JSON 格式传输数据。
// 支持通过 opts 参数自定义请求头（如 Bearer Token）。
// T 为响应体的结构体类型，自动解析 JSON 响应到 T。
// 用法：SendHttp[RespType](url, reqData, SetToken("token"), SetHeader("X-Header", "v"))
func SendHttp[T any](url string, data any, opts ...option) (result *T, reserr error) {
	j, _ := json.Marshal(data)
	req, err := http.NewRequest("POST", url, bytes.NewReader(j))
	if err != nil {
		return nil, err
	}
	req.Header.Set("Content-Type", "application/json")
	for _, opt := range opts {
		opt(req)
	}
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, err
	}
	tmp, err := io.ReadAll(res.Body)
	res.Body.Close()
	if err != nil {
		return nil, err
	}
	result = new(T)
	reserr = json.Unmarshal(tmp, result)
	return
}

// SendHttpByWWW 发送 HTTP POST 请求，使用 application/x-www-form-urlencoded 格式传输数据。
// 支持通过 opts 参数自定义请求头（如 Bearer Token）。
// T 为响应体的结构体类型，自动解析 JSON 响应到 T。
// 用法：SendHttpByWWW[RespType](url, formData, SetToken("token"))
func SendHttpByWWW[T any](url string, data url.Values, opts ...option) (result *T, reserr error) {
	req, err := http.NewRequest("POST", url, strings.NewReader(data.Encode()))
	if err != nil {
		return nil, err
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	for _, opt := range opts {
		opt(req)
	}
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, err
	}
	tmp, err := io.ReadAll(res.Body)
	res.Body.Close()
	if err != nil {
		return nil, err
	}
	result = new(T)
	reserr = json.Unmarshal(tmp, result)
	return
}

// StackTrace 获取当前 goroutine 的调用栈信息。
// 返回格式化后的调用栈字符串，便于调试。
func StackTrace() string {
	sb := NewStringBuilder()
	sb.Appendln("")
	sb.Appendln("\t\t[StackTrace]:")
	for i := 1; i < 40; i++ {
		pc, file, line, ok := runtime.Caller(i)
		if !ok {
			break
		}
		if strings.Contains(file, "/runtime/") {
			continue
		}
		sb.Appendln(fmt.Sprintf("\t\t%d. %s() %s:%d", i, runtime.FuncForPC(pc).Name(), file, line))
	}
	return sb.ToString()
}

// GetSystemUserName 获取当前系统用户的用户名。
// 获取失败时返回空字符串。
func GetSystemUserName() string {
	if us, err := user.Current(); err != nil {
		return ""
	} else {
		return us.Username
	}
}
